<template>
  <div class="month-wrap">
    <el-row>
      <el-button-group>
        <el-button>
          <b>{{ currentMonth }}</b>
        </el-button>
        <el-button type="primary" @click="calculateCurrentMonth">
          <b>当前月</b>
        </el-button>
        <el-button type="primary" @click="calculatePreviousMonth">
          <el-icon>
            <ele-ArrowLeft/>
          </el-icon>
          上一月
        </el-button>
        <el-button type="primary" @click="calculateNextMonth">
          <el-icon>
            <ele-ArrowRight/>
          </el-icon>
          下一月
        </el-button>
      </el-button-group>
    </el-row>
    <table>
      <tbody>
        <tr>
          <td class="header-item"
              v-for="(item, index) in weeks"
              :key="index"
              :style="{width: themeConfig.isCollapse ? 'calc((100vw - 140px) / 7)' : 'calc((100vw - 300px) / 7)'}">
            <span v-if="index === 0 || index === 6" class="color-red">{{ item }}</span>
            <span v-else>{{ item }}</span>
          </td>
        </tr>
        <tr v-for="(item, index) in days" :key="index + 'x'">
          <td class="cursor item-block"
              v-for="(it, idx) in item"
              :key="idx + 'c'"
              :style="{width: themeConfig.isCollapse ? 'calc((100vw - 140px) / 7)' : 'calc((100vw - 300px) / 7)'}"
              :class="!it.isNow ? 'none-current' : it.isHoliday? 'holiday-bg' : ''">
            <div class="block-wrap">
              <p class="day-span" :class="!it.current ? 'color-gray' : ''">
                <span v-if="idx === 0 || idx === 6" class="color-red">{{ it.day < 10 ? '0' + it.day : it.day }}</span>
                <span v-else>{{ it.day < 10 ? '0' + it.day : it.day }}</span>
                <span class="jieqi-name" v-if="it.isJieqi" @click="showJieqi(it)">{{ it.jieqiName }}</span>
                <span class="holiday" v-if="it.isHoliday">{{ it.holiday }}</span>
                <span class="xiu-tag" v-if="it.isHoliday">休</span>
                <span class="is-today" v-if="it.isToday">今日</span>
                <span class="lunar">{{ it.lunar }}</span>
              </p>
              <div v-if="it.data.length > 0">
                <div v-for="(i,d) in it.data"
                     :key="'dd' + d">
                  <slot name="default" :row="i"></slot>
                </div>
              </div>
              <div class="empty-schedule-wrap" v-else>
                <img :src="EmptyBox"/>
              </div>
            </div>
          </td>
        </tr>
      </tbody>
    </table>
    <HolidayInfo ref="holidayInfoRef"/>
    <div ref="jieQiInfoRef" :id="autoKey">
      <JieQiInfo v-if="showJieqiDetail" :detail="currentJieqi" :tag="autoKey"/>
    </div>
  </div>
</template>

<script lang="ts">
import {defineComponent, nextTick, reactive, toRefs, ref, onMounted} from 'vue';
import Config from './config';
import {getLunarDateByYMD, getLunarJieQiByYMD, getCurrentDate} from "/@/utils/formatTime";
import {getHolidayPage} from "/@/api/system/holiday";
import HolidayInfo from "/@/components/jcalendar/component/holidayInfo.vue";
import JieQiInfo from "/@/components/jcalendar/component/jieQiInfo.vue";
import {storeToRefs} from "pinia";
import {useThemeConfig} from "/@/stores/themeConfig";
import EmptyBox from "/@/assets/empty-box.svg";

interface CalendarDate {
  date: string;
  day: number;
  month: number;
  year: number;
  isNow: boolean;
  isToday: boolean;
  lunar: string;
  isHoliday: boolean,
  holiday: string,
  isJieqi: boolean,
  jieqiName: string,
  data: object
}

interface MyObject {
  [key: string]: any;
}

const props = {
  month: {
    type: String,
    default: () => {
      const now = new Date();
      const year = now.getFullYear();
      const month = (now.getMonth() + 1).toString().padStart(2, '0');
      return `${year}-${month}`;
    }
  }
};
export default defineComponent({
  name: 'Jcalendar',
  components: {HolidayInfo, JieQiInfo},
  props: props,
  setup(props, {emit}) {
    const jieQiInfoRef = ref();
    const holidayInfoRef = ref();
    const autoKey = ref("4565674")
    const storesThemeConfig = useThemeConfig();
    const {themeConfig} = storeToRefs(storesThemeConfig);
    const state = reactive({
      currentMonth: props.month,
      weeks: Config.weeks,
      days: [],
      holidays: {},
      showJieqiDetail: false,
      currentJieqi: {},
      data: {},
      originalData: []
    });
    onMounted(() => {
      nextTick(() => {
        calculateData([]);
      })
    });
    const getCurrentMonth = () => {
      return state.currentMonth;
    }
    // 获取财务日报信息
    const calculateData = (_data: any) => {
      state.originalData = _data;
      let _obj = {};
      if (_data.length > 0) {
        _data.forEach((item) => {
          const _key = item.date;
          if (!_obj.hasOwnProperty(_key)) {
            _obj[_key] = [];
          }
          _obj[_key].push(item);
        })
      }
      state.data = _obj;
      const [year, month] = state.currentMonth.split("-");
      getCalendarDates(parseInt(year), parseInt(month));
    };
    // 获取日历月的所有天
    const getCalendarDates = (year: number, month: number) => {
      const calendarDates: CalendarDate[] = [];
      const firstDay = new Date(year, month - 1, 1);
      const lastDay = new Date(year, month, 0);
      const startDay = firstDay.getDay(); // 月初是星期几
      const endDay = lastDay.getDate(); // 月末的日期
      // 补齐月初的日期
      for (let i = startDay - 1; i >= 0; i--) {
        const date = new Date(year, month - 1, -i);
        const _day = date.getFullYear() + "-"
            + (date.getMonth() + 1 < 10 ? ('0' + (date.getMonth() + 1)) : date.getMonth() + 1)
            + "-" + (date.getDate() ? ('0' + date.getDate()) : date.getDate());
        const _lunar = getLunarDateByYMD(_day);
        calendarDates.push({
          date: _day,
          day: date.getDate(),
          month: date.getMonth() + 1,
          year: date.getFullYear(),
          isNow: false,
          isToday: false,
          lunar: _lunar,
          isHoliday: false,
          holiday: '',
          isJieqi: false,
          jieqiName: '',
          data: []
        });
      }

      // 当月日期
      const _currentDate = getCurrentDate();
      for (let day = 1; day <= endDay; day++) {
        const date = new Date(year, month - 1, day);
        const _day = year + "-" + (month < 10 ? ('0' + month) : month) + "-" + (day < 10 ? ("0" + day) : day);
        const _lunar = getLunarDateByYMD(_day);
        const _jieqi = getLunarJieQiByYMD(_day);
        calendarDates.push({
          date: _day,
          day: day,
          month: month,
          year: year,
          isNow: true,
          isToday: _currentDate == _day,
          isHoliday: false,
          holiday: '',
          lunar: _lunar,
          isJieqi: _jieqi.length > 0,
          jieqiName: _jieqi,
          data: []
        });
      }

      // 补齐月末的日期
      const endWeekDay = lastDay.getDay(); // 月末是星期几
      for (let i = 1; i <= 6 - endWeekDay; i++) {
        const date = new Date(year, month, i);
        const _day = date.getFullYear() + "-"
            + (date.getMonth() + 1 < 10 ? ('0' + (date.getMonth() + 1)) : date.getMonth() + 1)
            + "-" + (date.getDate() ? ('0' + date.getDate()) : date.getDate());
        const _lunar = getLunarDateByYMD(_day);
        calendarDates.push({
          date: _day,
          day: date.getDate(),
          month: date.getMonth() + 1,
          year: date.getFullYear(),
          isNow: false,
          isToday: false,
          lunar: _lunar,
          isHoliday: false,
          holiday: '',
          isJieqi: false,
          jieqiName: '',
          data: []
        });
      }
      initCalendarDays(calendarDates);
    }
    // 按日历表格式每行分组
    const initCalendarDays = async (_list: CalendarDate[]) => {
      await getHolidaysFromRemote(_list[0].date, _list[_list.length - 1].date);
      state.days = [];
      let _t = []
      for (let i = 0; i < _list.length; i++) {
        const _idx = (i) % 7;
        const _date = _list[i].date;
        if (state.holidays.hasOwnProperty(_date)) {
          _list[i].isHoliday = true;
          _list[i].holiday = state.holidays[_date];
        }
        if (state.data.hasOwnProperty(_date)) {
          _list[i].data = state.data[_date];
        }
        _t.push(_list[i])
        if (_idx === 6 && i > 0) {
          state.days.push(_t)
          _t = []
        }
      }
    };
    // 按指定时间段远程获取节假日
    const getHolidaysFromRemote = async (_start: string, _end: string) => {
      await getHolidayPage({start: _start, end: _end, pageNum: 1, pageSize: 20}).then(res => {
        state.holidays = {};
        const _holidays = res.data.list
        if (_holidays.length > 0) {
          _holidays.forEach((item, index) => {
            state.holidays = {...getDatesBetweenDates(new Date(item.startDay), new Date(item.endDay), item.name), ...state.holidays}
          })
        }
      })
    }
    // 生成节假日中的每一天map
    const getDatesBetweenDates = (startDate: Date, endDate: Date, holiday: string) => {
      const dates: MyObject = {};
      let currentDate = new Date(startDate);

      while (currentDate <= endDate) {
        const _date = new Date(currentDate).toISOString().slice(0, 10);
        dates[_date] = holiday;
        currentDate.setDate(currentDate.getDate() + 1);
      }

      return dates;
    }
    // 跳转上一月
    const calculatePreviousMonth = () => {
      const [year, month] = state.currentMonth.split('-');
      if (parseInt(month) === 1) {
        state.currentMonth = `${parseInt(year) - 1}-12`;
      } else {
        state.currentMonth = `${parseInt(year)}-${(parseInt(month) - 1).toString().padStart(2, '0')}`;
      }
      calculateData([]);
      emit("updateDate", state.currentMonth);
    }
    // 跳转下一月
    const calculateNextMonth = () => {
      const [year, month] = state.currentMonth.split('-');
      if (parseInt(month) === 12) {
        state.currentMonth = `${parseInt(year) + 1}-01`;
      } else {
        state.currentMonth = `${parseInt(year)}-${(parseInt(month) + 1).toString().padStart(2, '0')}`;
      }
      calculateData([]);
      emit("updateDate", state.currentMonth);
    }
    // 跳转当前月
    const calculateCurrentMonth = () => {
      state.currentMonth = props.month;
      calculateData([]);
      emit("updateDate", state.currentMonth);
    }
    // 显示节气弹窗
    const showJieqi = (_item: string) => {
      state.showJieqiDetail = false
      state.currentJieqi = _item
      refreshAutoKey()
      state.showJieqiDetail = true
      nextTick(() => {
        const targetDiv = document.getElementById('app');
        const divToMove = jieQiInfoRef.value;
        targetDiv.parentNode.insertBefore(divToMove, targetDiv.nextSibling);
      })
    }
    const refreshAutoKey = () => {
      autoKey.value = new Date().getTime() + (Math.random() * 1000).toFixed(0);
    };
    return {
      autoKey,
      jieQiInfoRef,
      holidayInfoRef,
      ...toRefs(state),
      showJieqi,
      themeConfig,
      EmptyBox,
      calculateData,
      getCurrentMonth,
      calculatePreviousMonth,
      calculateNextMonth,
      calculateCurrentMonth,
    }
  }
})
;
</script>

<style scoped lang="scss">
.month-wrap {
  width: 100%;

  table {
    //border-collapse: collapse;
    width: 100%;
    table-layout: fixed;
  }

  table tbody {
    display: block;
    height: 80vh;
    overflow-y: auto;
  }

  td {
    border-top: 1px solid #e8eaec;
    border-right: 1px solid #e8eaec;
  }

  tr td:first-child {
    border-left: 1px solid #e8eaec;
  }
  tr:first-child td:first-child {
    border-left: none;
  }
  tr:last-child td {
    border-bottom: 1px solid #e8eaec;
  }

  .header-item {
    font-weight: bold;
    border: none;
    padding: 10px 0 10px;
    text-align: center;
  }

  .color-red {
    color: #eb3333;
  }

  .item-block {
    &:hover {
      background-color: rgba(240, 250, 255, 0.2);
    }
  }

  .none-current {
    background-color: rgba(246, 246, 246, 0.2) !important;
  }

  .holiday-bg {
    background-color: rgba(235, 51, 51, 0.07);
  }

  .none-current {
    background-color: grey;
  }

  .block-wrap {
    width: 100%;
    height: 150px;
    display: block;
    position: relative;
    overflow-y: auto;
    padding: 5px;

    .day-span {
      position: sticky;
      top: 0;
      left: 0;
      z-index: 2;
      padding-bottom: 5px;
      font-size: 16px;
      font-weight: bold;
      display: flex;
      justify-content: space-between;

      .jieqi-name {
        font-size: 12px;
        padding: 2px 5px;
        border-radius: 3px;
        background-color: #4e5877;
        color: #ffffff;
        cursor: pointer;
      }

      .holiday {
        font-size: 12px;
        padding: 2px 5px;
        border-radius: 3px;
        background-color: #4cb0e4;
        color: #ffffff;
      }

      .xiu-tag {
        font-size: 12px;
        padding: 2px 5px;
        border-radius: 3px;
        background-color: #eb3333;
        color: #ffffff;
      }

      .is-today {
        font-size: 12px;
        padding: 2px 5px;
        border-radius: 3px;
        background-color: #e91e63;
        color: #ffffff;
      }

      .lunar {
        font-size: 12px;
        font-weight: bold;
      }
    }

    .empty-schedule-wrap {
      width: 100%;
      height: 80px;
      text-align: center;
      line-height: 80px;
      display: flex;
      justify-content: center;
      align-items: center;

      img {
        height: 40px;
      }
    }
  }
}
</style>
